#pragma once
#include<iostream>
#include<semaphore.h>
#include<pthread.h>
#include<unistd.h>
#include<vector>
#include<stdlib.h>

namespace ring_queue
{
    const int default_cap = 10;
    const int default_sem_val = 10;
    template<class T>
    class RingQueue
    {
    private:
        std::vector<T> _ring_queue;
        int _cap;//队列资源数

        //生产者关心空位置资源
        sem_t _blank_sem;
        // 消费者关心空位置资源
        sem_t _data_sem;

        int _c_step;//消费者的位置
        int _p_step;//生产者的位置

    public:
        void pop(T *const data)//消费者取出数据
        {
            sem_wait(&_data_sem);//申请数据信号量
            
            //这里消费数据
            *data = _ring_queue[_c_step];
            //更新消费者指向数据位置
            _c_step++;
            _c_step %= _cap;
            
            sem_post(&_blank_sem);//消费数据后，增加一个空位量

        }
        void push(const T& data)//生产者生产数据
        {
            sem_wait(&_blank_sem);//申请空位信号量

            //这里生产数据
            _ring_queue[_p_step] = data;
            //更新生产者指向空盘位置
            _p_step++;
            _p_step %= _cap;

            sem_post(&_data_sem);//放入数据后，增加一个数据信号量
        }
    public:
        RingQueue(int cap = default_cap): _ring_queue(cap), _cap(cap)
        {
            //信号量初始化
            sem_init(&_blank_sem, 0, cap);//空位初始和容量一个大小
            sem_init(&_data_sem, 0, 0);//数据量初始为0
        }
        ~RingQueue()
        {
            sem_destroy(&_blank_sem);
            sem_destroy(&_data_sem);
        }
    };
}